package com.yundou.www.wrpc.core.net;

import com.alibaba.fastjson.JSON;
import com.yundou.www.wrpc.core.config.ClientConfig;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.LineEncoder;
import io.netty.handler.codec.string.LineSeparator;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;


import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author wangweiwei
 * @since 2021/7/22
 */
public class NettyClient {

    private ClientConfig config;

    private NioEventLoopGroup work;

    private Bootstrap bootstrap ;

    private Channel channel;

    private CountDownLatch countDownLatch = null;

    public NettyClient(ClientConfig config) {
        this.config = config;
    }



    public void connection(CountDownLatch countDownLatch) {

        AtomicInteger atomicInteger = new AtomicInteger(1);

        work = new NioEventLoopGroup();

        bootstrap = new Bootstrap();

        bootstrap.group(work);

        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.TCP_NODELAY , Boolean.TRUE);

            bootstrap.handler(new ChannelInitializer<Channel>() {

                @Override
                protected void initChannel(Channel channel) {

                    ChannelPipeline pipeline = channel.pipeline();
                    //添加字符串的编解码器
                    ByteBuf buf = Unpooled.copiedBuffer("$".getBytes(StandardCharsets.UTF_8));
                    pipeline.addLast(new DelimiterBasedFrameDecoder(1024 , buf));
                    pipeline.addLast(new StringDecoder());
                    pipeline.addLast(new StringEncoder());

                    pipeline.addLast(new ClientBusinessHandler());

                }
            });

            try {

                ChannelFuture future = bootstrap.connect(config.getIp(), config.getPort()).sync();

                future.addListener(new ChannelFutureListener() {


                    @Override
                    public void operationComplete(ChannelFuture channelFuture) throws Exception {
                        if (channelFuture.isSuccess()) {

                            System.out.println("连接词和共和国");
                            if (countDownLatch!= null) {
                                countDownLatch.countDown();
                            }
                        }
                    }
                });
                this.channel = future.channel();

                future.channel().closeFuture().sync();
            } catch (Exception e ) {
                e.printStackTrace();
            }


    }

    public void heardCheck() {
        if (channel == null ) {
            countDownLatch = new CountDownLatch(1);
            connection(countDownLatch);
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else if (!channel.isOpen()) {
            countDownLatch = new CountDownLatch(1);
            connection(countDownLatch);
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        WRpcRequest request = new WRpcRequest();
        request.setCheckSession(1);
        channel.writeAndFlush(JSON.toJSONString(request));
    }

    public void doRequest(WRpcRequest request) {
        if (channel == null ) {
            countDownLatch = new CountDownLatch(1);
            connection(countDownLatch);
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (!channel.isOpen()) {
            countDownLatch = new CountDownLatch(1);
            connection(countDownLatch);
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(channel.isOpen());
        String s = JSON.toJSONString(request)+"$";
        System.out.println(s);
        channel.writeAndFlush(s);

    }
}
